package com.yuandian.management.service.impl;

import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yuandian.api.customer_perception.po.BusinessAnalysisParams;
import com.yuandian.api.customer_perception.vo.BusinessStepAnalysisVo;
import com.yuandian.api.management.entity.ConfResource;
import com.yuandian.api.management.entity.ConfStep;
import com.yuandian.api.management.vo.OptionVo;
import com.yuandian.bpm.common.core.util.R;
import com.yuandian.bpm.common.security.util.SecurityUtils;
import com.yuandian.enums.ResultCodeEnum;
import com.yuandian.management.dto.ConfStepDTO;
import com.yuandian.management.mapper.ConfStepMapper;
import com.yuandian.management.service.ConfResourceService;
import com.yuandian.management.service.ConfStepService;
import com.yuandian.utils.ListUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * 步骤配置表-Service实现
 *
 * @author zfsn
 * @date 2023-3-14
 */
@Slf4j
@Service
public class ConfStepServiceImpl extends ServiceImpl<ConfStepMapper, ConfStep>
		implements ConfStepService {

	@Lazy
	@Autowired
	private ConfStepMapper confStepMapper;

	@Autowired
	public ConfResourceService confResourceService;

	/**
	 * 通过业务编码删除步骤
	 *
	 * @param businessCodes 业务编码
	 */
	@Override
	public Integer removeStepByBusinessCodes(List<String> businessCodes) {
		return confStepMapper.removeStepByBusinessCodes(businessCodes);
	}

	/**
	 * 分页查询
	 *
	 * @param confStep 筛选条件
	 * @return 通用返回对象
	 */
	@Override
	public Page<ConfStep> listPage(ConfStep confStep) {
		return confStepMapper.listPage(new Page<>(confStep.getPageNum(), confStep.getPageSize()), confStep);
	}

	/**
	 * 新增数据
	 *
	 * @param confStep 实例对象
	 * @return 通用返回对象
	 */
	@Override
	public R<String> saveStep(ConfStep confStep) {
		if (checkStepNameDuplicates(confStep)) {
			log.warn("步骤名称：{}存在重复", confStep.getName());
			return R.failed(ResultCodeEnum.STEP_NAME_EXIST.getMsg());
		}
		if (checkResourceDuplicates(confStep)) {
			log.warn("业务资源：{}存在重复", confStep.getName());
			return R.failed(ResultCodeEnum.STEP_RESOURCE_EXIST.getMsg());
		}
		try {
			confStep.setCreateBy(SecurityUtils.getUser().getName());
		}catch (Exception e){
			log.error(e.getMessage(), e);
			confStep.setCreateBy("admin");
		}

		super.save(confStep);
		return R.ok();
	}

	/**
	 * 通过主键更新数据
	 *
	 * @param confStep 实例对象
	 * @return 通用返回对象
	 */
	@Override
	public R<Boolean> updateStepById(ConfStep confStep) {
		if (checkStepNameDuplicates(confStep)) {
			log.warn("步骤名称：{}存在重复", confStep.getName());
			return R.failed(ResultCodeEnum.STEP_NAME_EXIST.getMsg());
		}
		if (checkResourceDuplicates(confStep)) {
			log.warn("业务资源：{}存在重复", confStep.getName());
			return R.failed(ResultCodeEnum.STEP_RESOURCE_EXIST.getMsg());
		}
		super.updateById(confStep);
		return R.ok();

	}

	/**
	 * 通过主键删除数据
	 *
	 * @param ids
	 * @return 通用返回对象
	 */
	@Override
	public boolean removeByIds(List<Integer> ids) {
		List<String> stepCodes = super.listByIds(ids).stream().map(ConfStep::getStepCode).collect(Collectors.toList());
		confResourceService.confirmResource(stepCodes, false);
		return super.removeByIds(ids);
	}

	/**
	 * 通过主键确认步骤
	 *
	 * @param ids       主键
	 * @param isConfirm
	 * @return 通用返回对象
	 */
	@Override
	public R<String> confirm(List<Integer> ids, boolean isConfirm) {
		int status = isConfirm ? 1 : 0;
		UpdateWrapper<ConfStep> updateWrapper = new UpdateWrapper<>();
		updateWrapper.set("is_confirm", status);
		updateWrapper.in("id", ids);
		if (!super.update(updateWrapper)) {
			R.failed("更新失败,请重新更新");
		}
		if (isConfirm) {
			List<ConfStep> confSteps = super.listByIds(ids);
			if (!CollectionUtils.isEmpty(confSteps)){
				List<String> stepCodes = confSteps.stream().map(ConfStep::getStepCode).collect(Collectors.toList());
				confResourceService.confirmResource(stepCodes, true);
				//批量修改资源状态
				LambdaUpdateWrapper<ConfResource> lambdaUpdate = Wrappers.lambdaUpdate();
				lambdaUpdate.set(ConfResource::getType, 2);
				lambdaUpdate.set(ConfResource::getIsConfirm, 1);
				lambdaUpdate.in(ConfResource::getResourceCode, stepCodes);
				confResourceService.update(lambdaUpdate);
			}

		}
		return R.ok();
	}

	/**
	 * 查询业务步骤类型
	 *
	 * @return 通用返回对象
	 */
	@Override
	public Map<String, String> queryStepTypeByBusinessCode() {
		Map<Integer, String> stepTypeMap = new HashMap<>();
		stepTypeMap.put(1, "首步骤");
		stepTypeMap.put(2, "中间步骤");
		stepTypeMap.put(3, "末步骤");
		Map<String, String> map = new HashMap<>();
		List<ConfStepDTO> confStepDTOList = confStepMapper.getStepTypeAndBusinessCode();
		// 转化 Map<业务编码@步骤编码, 步骤类型> 的形式
		if (!CollectionUtils.isEmpty(confStepDTOList)) {
			for (ConfStepDTO dto : confStepDTOList) {
				map.put(dto.getBusinessStep(), stepTypeMap.get(dto.getStepType()));
			}
		}
		return map;
	}

	/**
	 * 查询步骤
	 *
	 * @param confStep
	 * @return 通用返回对象
	 */
	@Override
	public List<ConfStep> getStepBySystemIdAndStepCode(ConfStep confStep) {
		return confStepMapper.getStepBySystemIdAndStepCode(confStep);
	}

	/**
	 * 查询步骤编码和名称
	 *
	 * @param confStep
	 * @return 通用返回对象
	 */
	@Override
	public List<ConfStep> getResourceCodeBySystemIdOrStepCode(ConfStep confStep) {
		return confStepMapper.getStepBySystemIdAndStepCode(confStep);
	}

	/**
	 * 判断业务名称是否重复
	 *
	 * @param confStep 业务对象
	 */
	private boolean checkStepNameDuplicates(ConfStep confStep) {
		QueryWrapper<ConfStep> queryWrapper = new QueryWrapper<>();
		queryWrapper.eq("name", confStep.getName());
		queryWrapper.eq("business_code", confStep.getBusinessCode());
		Integer id = confStep.getId();
		if (ObjectUtil.isNotEmpty(id)) {
			queryWrapper.ne("id", id);
		}
		return super.count(queryWrapper) > 0;
	}

	/**
	 * 判断业务名称是否重复
	 *
	 * @param confStep 业务对象
	 */
	private boolean checkResourceDuplicates(ConfStep confStep) {
		QueryWrapper<ConfStep> queryWrapper = new QueryWrapper<>();
		queryWrapper.eq("business_code", confStep.getBusinessCode());
		queryWrapper.eq("step_code", confStep.getStepCode());
		if (confStep.getId() != null){
			queryWrapper.ne("id", confStep.getId());
		}
		return super.count(queryWrapper) > 0;
	}

	/**
	 * 查询共用步骤的步骤编码和步骤名称
	 *
	 * @return 通用返回对象
	 */
	@Override
	public List<OptionVo> queryPublicStepOptions() {
		return confStepMapper.queryPublicStepOptions();
	}


	/**
	 * 查询系统id
	 *
	 * @return 通用返回对象
	 */
	@Override
	public List<String> querySystemIdByStepCode(List<String> stepCodes) {
		return confStepMapper.querySystemIdByStepCode(stepCodes);
	}

	@Override
	public List<ConfStep> getStepByBusinessCodes(ConfStep confStep) {

		return confStepMapper.getStepByBusinessCodes(confStep);
	}

	/**
	 * 查询同一系统共用步骤的业务
	 *
	 * @param stepCode 步骤编码
	 * @param stepId
	 * @param systemId
	 * @return 通用返回对象
	 */
	@Override
	public R getShareBusiness(String stepCode, Integer systemId, Integer stepId) {
		return R.ok(confStepMapper.getShareBusiness(stepCode, systemId, stepId));
	}

	@Override
	public ConfStep saveBusinessProcess(ConfStep process) {
		Integer id = process.getId();
		if (Objects.nonNull(id)) {
			ConfStep oldConfStep = super.getById(id);
			if (Objects.nonNull(oldConfStep)) {
				ConfStep confStep = createConfStep(process);
				confStep.setId(id);
				updateStepById(confStep);
			}
		} else {
			ConfStep confStep = createConfStep(process);
			saveStep(confStep);
		}

		return process;
	}

	private ConfStep createConfStep(ConfStep process) {
		ConfStep confStep = new ConfStep();
		confStep.setIsConfirm(process.getIsAllowFail());
		confStep.setName(process.getName());
		confStep.setSystemId(process.getSystemId());
		confStep.setBusinessCode(process.getBusinessCode());
		confStep.setStepCode(process.getStepCode());
		confStep.setType(process.getType());
		confStep.setIsAllowFail(process.getIsAllowFail());
		confStep.setIsCombinedStrategy(process.getIsCombinedStrategy());
		confStep.setSequence(process.getSequence());

		return confStep;
	}

	/**
	 * 根据业务编码查询对应业务步骤信息
	 * @param params
	 * @return
	 */
	@Override
	public List<BusinessStepAnalysisVo> selectStepsByBusicessCode(BusinessAnalysisParams params) {
		return this.baseMapper.selectStepsByBusicessCode(params);
	}
}
